#include "Moving Entity.h"
#include "Entity Manager.h"
#include "Steering Behavior.h"
#include "GameWorld.h"
#include "Defines.hpp"

#define CharacterSpeed 10
//#define PI 3.141592653589793238462643383279 // Because I can

// One up.  Seriously.  Its not even possible to beat me.
//#define PI 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844

// You do realize that it's not even possible for the computer to calculate with that, right? I doubt it could
// accurately handle mine. (maybe with a long double, but even that I doubt)

#define PI 3.14159




MovingEntity::MovingEntity(string name, Vector2D pos, int type) :	BaseGameEntity(pos, name, type)
{
	// The Bound Radius should be the inscribed circle but a certain ratio (3.0) smaller (as that's to big)
	SetBRadius((sqrt(float(this->GetWidth() * this->GetWidth() + this->GetHeight() * this->GetHeight()))/2.0/3.0));
	
	m_pSteeringBehavior = new SteeringBehavior(this);
	m_pPlanner = new PathPlanner(this);
}

MovingEntity::~MovingEntity()
{
	NullDelete(m_pSteeringBehavior);
	NullDelete(m_pPlanner);
}

void MovingEntity::Render()
{
	BaseGameEntity::Render();
}

void MovingEntity::Update(double time_elapsed)
{
	BaseGameEntity::Update(time_elapsed);

	Vector2D acceleration = m_pSteeringBehavior->Calculate();

	velocity += acceleration;
	velocity.Truncate(CharacterSpeed);

	Vector2D OldPos = m_vPos;

	if(velocity.Length() > 1)
	{
		m_vPos.x += (velocity.x); /**(time_elapsed/60.0f)*/;
		m_vPos.y += (velocity.y);

	}


	m_animationAngle = atan(velocity.y/velocity.x) * (180.0/PI);
	if(velocity.x < 0)
		m_animationAngle -= 180;

	if(velocity.Length() <= 1)
		StopAnimating();
	else
		ResumeAnimation();


	this->ChangeX(Sint16(m_vPos.x - (this->GetWidth()/2)));
	this->ChangeY(Sint16(m_vPos.y - (this->GetHeight()/2)));
	
	if(m_vPos != OldPos)
	{
		World->EnforceNonPenetration(this);
		WorldMap->GetPartition().UpdateEntity(this, OldPos);
		World->UpdateMinimapEntity(this->ID(), Vector2D(this->GetX(), this->GetY()));
	}
	

	if(velocity.Length() > 1)
		isMoving = true;
	else
		isMoving = false;
}

bool MovingEntity::CanMoveBetween(Vector2D Start, Vector2D Finish)
{
	return !(World->IsPathObstructed(Start, Finish, BRadius()));
}

void MovingEntity::SetBehaviorTarget(Vector2D pos)
{ 
	m_pSteeringBehavior->SetTarget(pos);
}


